/*
* Copyright 2018 Shanxi Lu'an Taihang Laihui Net Tech co.,LTD.
*/
package com.laihuichuxing.order.handle;

import com.laihuichuxing.caocao.CaocaoClient;
import com.laihuichuxing.caocao.DefaultCaocaoClient;
import com.laihuichuxing.caocao.request.CaocaoOrderCarRequest;
import com.laihuichuxing.caocao.response.CaocaoOrderCarResponse;
import com.laihuichuxing.common.config.CacheConfig;
import com.laihuichuxing.order.concurrent.BasicThreadPool;
import com.laihuichuxing.order.concurrent.ThreadPool;
import com.laihuichuxing.order.dao.DriverOrderDao;
import com.laihuichuxing.order.dao.PassengerOrderDao;
import com.laihuichuxing.order.util.NettyConst;
import com.laihuichuxing.pool.DriverLbs4MongoPool;
import com.laihuichuxing.pool.UserLbs4MongoPool;
import com.laihuichuxing.pool.conf.CaocaoConfig;
import com.laihuichuxing.pool.dto.DriverLbsDto;
import com.laihuichuxing.pool.dto.UserLbsDto;
import com.laihuichuxing.protobuf.module.OrderModule;
import com.laihuichuxing.socket.LbsCmd;
import com.laihuichuxing.socket.ModuleId;
import com.laihuichuxing.socket.NettyClient;
import com.laihuichuxing.socket.Request;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Description:
 *
 * @author: Qinxuefeng
 * @since: 1.0
 * Create Date Time: 2018/11/2 16:56
 * Update Date Time:
 */
@Service
public class UserHandler4Mongo {
    private Logger logger = LoggerFactory.getLogger(UserHandler4Mongo.class);
    @Autowired
    private UserLbs4MongoPool userLbsPool;
    @Autowired
    private DriverLbs4MongoPool driverLbsPool;
    @Autowired
    private NettyConst nettyConst;
    @Autowired
    private PassengerOrderDao passengerOrderDao;
    @Autowired
    private DriverOrderDao driverOrderDao;
    @Autowired
    private DriverHandler4Mongo driverHandle;
    @Autowired
    private CaocaoConfig caocaoConfig;
    /**
     * 初始化
     */
    private CaocaoClient caocaoClient;
    {
        caocaoClient = new DefaultCaocaoClient(com.laihuichuxing.caocao.CaocaoConfig.TRUE);
    }
    /**
     * 创建线程池，initSize 初始大小 maxSize 最大大小 coreSize 核心大小 queueSize任务队列大小
     */
    private final static ThreadPool threadPool = new BasicThreadPool(10, 1000, 40, 10000);

    public void task(UserLbsDto user,int count) {
        DriverLbsDto driver = new DriverLbsDto();
        driver.setCityZone(user.getCityZone());
        threadPool.execute(() -> {
                    try {
                        String mobile = userLbsPool.takeMe(user.getPhone(),user.getCityZone());
                        if (!"".equals(mobile)) {
                            //匹配到司机
                            DriverLbsDto driverLbsDto = driverLbsPool.take(user);
                            if (driverLbsDto!=null) {
                                //长连接通知
                                String passengerPhone = user.getPhone();
                                String driverPhone = driverLbsDto.getPhone();
                                // 查询乘客订单编号
                                String orderId = passengerOrderDao.selectPassengerOrderId(passengerPhone,1);
                                //修改数据库
                                updateSql(driverPhone, orderId);
                                this.putNetty2Notify(driverPhone, passengerPhone, orderId);
                                shutdown(user,orderId);

                            } else {
                                //未匹配到司机时继续匹配
                                getDriver(user,count);
                                //
                            }
                            //判断是否有合适资源
                        }
                    } catch (Exception e) {
                        logger.error("任务处理失败,异常信息为:{}", e.toString(), e);
                    }
                }
        );
    }

    public void task1(UserLbsDto user,int count) {
        DriverLbsDto driver = new DriverLbsDto();
        driver.setCityZone(user.getCityZone());
        threadPool.execute(() -> {
                    try {
                        String mobile = userLbsPool.takeMe(user.getPhone(),user.getCityZone());
                        if (!"".equals(mobile)) {
                            //匹配到司机
                            DriverLbsDto driverLbsDto = driverLbsPool.take(user);
                            if (driverLbsDto!=null) {
                                //长连接通知
                                String passengerPhone = user.getPhone();
                                String driverPhone = driverLbsDto.getPhone();
                                this.putNetty2Notify(driverPhone, passengerPhone, "111");
                                //去掉用户lbs
                                userLbsPool.del(user.getPhone(), user.getCityZone());
                            } else {
                                //未匹配到司机时继续匹配
                                getDriver1(user,count);
                            }
                            //判断是否有合适资源
                        }
                    } catch (Exception e) {
                        logger.error("任务处理失败,异常信息为:{}", e.toString(), e);
                    }
                }
        );
    }

    private void updateSql(String driverPhone, String orderId) {
        String driverId = driverOrderDao.selectDriverId(driverPhone);
        driverOrderDao.updateWyOrder(orderId, driverId);
        driverOrderDao.updateWyDriver(driverPhone);
    }
    /**
     * Description: 给曹操派单
     * @param  cached 接口数据
     * @return
     * @author QinXueFeng
     * Create Date Time: 2018/11/7 14:56
     * Update Date Time:
     */
    private boolean dispatch4Caocao(Map<String, Object> cached,UserLbsDto userLbsDto) {
        String address = cached.get("Address").toString();
        String adcode = cached.get("adcode").toString();
        Integer count = driverOrderDao.findCaocaoCity(address,adcode);
        if(count<1){
            return false;
        }
        Map<String,String> param=new HashMap<>();
        String orderId = cached.get("OrderId").toString();
        param.put("from_longitude",String.valueOf(Double.parseDouble(cached.get("DepLongitude").toString())/1000000));
        param.put("from_latitude",String.valueOf(Double.parseDouble(cached.get("DepLatitude").toString())/1000000));
        param.put("to_longitude",String.valueOf(Double.parseDouble(cached.get("DestLongitude").toString())/1000000));
        param.put("to_latitude",String.valueOf(Double.parseDouble(cached.get("DestLatitude").toString())/1000000));
        param.put("car_type","2");
        param.put("ext_order_id", orderId);
        param.put("caller_phone",userLbsDto.getPhone());
        param.put("city_code", address);
        param.put("adcode",adcode);
        param.put("order_type","1");
        param.put("start_name",cached.get("Departure").toString());
        param.put("end_name",cached.get("Destination").toString());
        CaocaoOrderCarRequest orderCarRequest = new CaocaoOrderCarRequest();
        orderCarRequest.setTextParams(param);
        // 执行请求,获取返回数据
        try {
            CaocaoOrderCarResponse execute = caocaoClient.execute(orderCarRequest);
            if(execute.isSuccess()){
                String orderNo = execute.getData().get("orderNo").toString();
                driverOrderDao.updateFlage(orderNo,orderId,2);
                shutdown(userLbsDto,orderId);
                return true;
            }
        } catch (Exception e) {
            logger.error("曹操接口派单失败{}",e.toString(),e);
        }
        return false;
    }
    /**
     * Description: 长连接通知司机和乘客
     *
     * @param driverPhone    司机手机号
     * @param passengerPhone 乘客手机号
     * @param orderId        订单编号
     * @author: YangGuang
     * Create Date Time: 2018/10/15 9:24
     * Update Date Time:
     */
    private void putNetty2Notify(String driverPhone, String passengerPhone, String orderId) {
        // 序列化数据
        OrderModule.Order order = OrderModule.Order.newBuilder().setOrderId(orderId).setDriverMobile(driverPhone).setPassengerMobile(passengerPhone).build();
        // 封装请求
        Request request = Request.valueOf(ModuleId.LBS, LbsCmd.DRIVER_ORDER, order.toByteArray());
        // 初始化客户端
        NettyClient nettyClient = new NettyClient(nettyConst.getAddress(), nettyConst.getPort());
        // 连接长连接
        try {
            nettyClient.connect();
            // 给客户端发消息
            nettyClient.sendRequest(request);
        } catch (InterruptedException e) {
            logger.error("派单成功连接长连接异常:{}", e.toString(), e);
            Thread.currentThread().interrupt();
        } finally {
            // 关闭连接
            nettyClient.shutdown();
        }
    }

    private void getDriver1(UserLbsDto user,int count) throws InterruptedException {
        String mobile = userLbsPool.takeMe(user.getPhone(),user.getCityZone());
        if (StringUtils.isNotEmpty(mobile)) {
            TimeUnit.SECONDS.sleep(5);
            ++count;
            if (count <= 5) {
                task(user,count);
            }
        }
    }

    /**
     * Description: 重复匹配司机
     * Author: Qinxuefeng
     * Version: 1.0
     * Create Date Time: 2018/10/15 17:32.
     * Update Date Time:
     */
    private void getDriver(UserLbsDto user,int count) throws InterruptedException {
        String mobile = userLbsPool.takeMe(user.getPhone(),user.getCityZone());

        if (StringUtils.isNotEmpty(mobile)) {
            Map<String,Object> map = passengerOrderDao.selectOrder(user.getPhone(),1);
            if(map==null){

                return;
            }
            if(caocaoConfig.getFlag()&&count>caocaoConfig.getTrial()){
                boolean flag=dispatch4Caocao(map,user);
                if(!flag){
                    count++;
                    task(user,count);
                }
            }else{
                TimeUnit.SECONDS.sleep(5);
                count++;
                task(user,count);
            }
        }
    }



    /**
     * Description: 取消匹配
     * Author: Qinxuefeng
     * Version: 1.0
     * Create Date Time: 2018/10/15 17:32.
     * Update Date Time:
     */
    public Boolean shutdown(UserLbsDto user,String orderId) {
        //去掉用户lbs
        userLbsPool.del(user.getPhone(), user.getCityZone());
        //cacheUtil.del(CacheConfig.PASSENGER+user.getPhone());
        //长连接通知司机
        if("2".equals(user.getUserStatus())){
            String driverPhone = driverOrderDao.selectDriverPhone(orderId);
            OrderModule.Order order = OrderModule.Order.newBuilder()
                    .setOrderId(orderId).setDriverMobile(driverPhone).build();
            driverHandle.shutdown(user.getCityZone(),driverPhone);
            // 封装请求
            Request request = Request.valueOf(ModuleId.LBS, LbsCmd.PASSENGER_CANCEL, order.toByteArray());
            // 初始化客户端
            NettyClient nettyClient = new NettyClient(nettyConst.getAddress(),nettyConst.getPort());
            // 连接长连接
            try {
                nettyClient.connect();
                // 给客户端发消息
                nettyClient.sendRequest(request);
            } catch (InterruptedException e) {
                logger.error("取消订单长连接异常:{}",e.toString(),e);
                Thread.currentThread().interrupt();
            } finally {
                // 关闭连接
                nettyClient.shutdown();
            }
        }
        return true;
    }

}
